package com.mtgdeckbuilder.server;

import static com.mtgdeckbuilder.shared.WizardGathererSiteUtil.baseGathererUrl;
import static com.mtgdeckbuilder.shared.WizardGathererSiteUtil.searchGathererUrl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

import com.mtgdeckbuilder.shared.StringUtil;
import com.mtgdeckbuilder.shared.dto.CardDTO;

/**
 * A source that represents the Magic The Gathering Gatherer website
 * 
 * @author Nicolas Deslandes
 */
public class WizardGathererWebsiteImpl extends MagicSource {

   @Override
   public List<CardDTO> query(final CardDTO args, final int limit) throws IOException {
      return getMultipleResult(args, limit);
   }

   private CardDTO getSingleResult(final CardDTO args) throws IOException {
      final CardDTO card = new CardDTO();
      final Document doc = getGathererHtmlSearchByName(args.getName());
      card.setMultiverseId(Long.valueOf(doc.select("#aspnetForm").attr("action").split("=")[1]));
      card.setName(doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_nameRow > div.value").text());
      card.setType(doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_typeRow > div.value").text());
      card.setText(doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_textRow > div.value").text());

      card.setEdition(doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_currentSetSymbol > a > img").attr("src").replace("../..", baseGathererUrl));
      card.setArtist(doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_ArtistCredit > a").text());

      card.setOtherEditions(new ArrayList<String>());
      for (final Object o : doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_otherSetsValue > a > img").toArray()) {
         final Element e = (Element) o;
         card.getOtherEditions().add(e.attr("src").replace("../..", baseGathererUrl));
      }

      final StringBuilder cost = new StringBuilder();
      boolean first = true;
      for (final Object o : doc.select("#ctl00_ctl00_ctl00_MainContent_SubContent_SubContent_manaRow > div.value > img").toArray()) {
         final Element e = (Element) o;
         if (!first) {
            cost.append("*");
         }
         cost.append(toTextualRepresentation(e.attr("alt")));
         first = false;
      }
      card.setCost(cost.toString());
      return card;
   }

   private List<CardDTO> getMultipleResult(final CardDTO args, final int limit) throws IOException {
      final Document doc = getGathererHtmlSearchByName(args.getName());
      final List<CardDTO> cards = new ArrayList<CardDTO>();
      if (StringUtil.isNumeric(doc.select("#aspnetForm").attr("action").split("=")[1])) {
         final CardDTO card = getSingleResult(args);
         cards.add(card);
      } else {
         int index = 0;
         for (final Object o : doc.select("tr.cardItem").toArray()) {
            final Element e = (Element) o;
            final CardDTO card = new CardDTO();
            card.setMultiverseId(Long.valueOf(e.select("[id$=cardImageLink]").attr("href").split("=")[1]));
            card.setName(e.select("[id$=cardTitle]").text());
            card.setType(e.select(".typeLine").text());
            card.setText(e.select(".rulesText").text());

            final StringBuilder cost = new StringBuilder();
            boolean first = true;
            for (final Object o1 : e.select(".manaCost > img").toArray()) {
               final Element e1 = (Element) o1;
               if (!first) {
                  cost.append("*");
               }
               cost.append(toTextualRepresentation(e1.attr("alt")));
               first = false;
            }
            card.setCost(cost.toString());
            card.setEdition(e.select("[id$=cardSetCurrent] > a > img").attr("src").replace("../..", baseGathererUrl));

            card.setOtherEditions(new ArrayList<String>());
            for (final Object o2 : e.select("[id$=cardSets] > a > img").toArray()) {
               final Element e2 = (Element) o2;
               card.getOtherEditions().add(e2.attr("src").replace("../..", baseGathererUrl));
            }

            cards.add(card);
            index++;
            if (index == limit) {
               break;
            }
         }
      }
      return cards;
   }

   private Document getGathererHtmlSearchByName(final String name) throws IOException {
      final String[] nameSplit = name.split(" ");
      final StringBuilder criteria = new StringBuilder("?");
      criteria.append("name=");
      for (final String element : nameSplit) {
         criteria.append("+[" + element + "]");
      }
      final Document doc = Jsoup.connect(searchGathererUrl + criteria.toString()).get();

      return doc;
   }

   private String toTextualRepresentation(final String wizardRepresentation) {
      String temp = wizardRepresentation;
      temp = wizardRepresentation.replace(" or ", "");
      temp = temp.replace("White", "W");
      temp = temp.replace("Blue", "U");
      temp = temp.replace("Black", "B");
      temp = temp.replace("Red", "R");
      temp = temp.replace("Green", "G");
      return temp;

   }
}
